package it.tukano.swingdeco.controls;

import it.tukano.fun.Function1;
import it.tukano.swingdeco.ExtUtilities;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.ButtonGroup;
import javax.swing.Icon;
import javax.swing.JToggleButton;
import javax.swing.SwingConstants;

/**
 * JToggleButton extension
 * @author pgi
 */
public class JToggleButtonExt extends JToggleButton {

    /* Serial version of this class */
    private static final long serialVersionUID = 0;

    /** Some kind of data associated with this control */
    private Object userObject;

    /**
     * Instance initializer
     */
    public JToggleButtonExt() {
    }

    /**
     * Executes a task when the selected state of this button changes
     * @param task the task to execute
     * @return this
     */
    public JToggleButtonExt onSelectedStateChange(final Runnable task) {
        addItemListener(new ItemListener() {

            public void itemStateChanged(ItemEvent e) {
                task.run();
            }
        });
        return this;
    }

    /**
     * Set the icon of this button
     * @param icon the icon to set
     * @return this
     */
    public JToggleButtonExt withIcon(Icon icon) {
        setIcon(icon);
        return this;
    }

    /**
     * Initializes this button with a label
     * @param label the label of the button
     */
    public JToggleButtonExt(String label) {
        super(label);
    }

    /**
     * Executes an action when the selected state changes to true
     * @param task the task to execute
     * @return this
     */
    public JToggleButtonExt onSelected(final Runnable task) {
        return onSelectedStateChange(new Runnable() {

            public void run() {
                if(isSelected()) task.run();
            }
        });
    }

    /**
     * Executes an action when the selected state changes to false
     * @param task the task to execute
     * @return this
     */
    public JToggleButtonExt onDeselected(final Runnable task) {
        return onSelectedStateChange(new Runnable() {

            public void run() {
                if(!isSelected()) task.run();
            }
        });
    }

    /**
     * Initializes the button with a default icon
     * @param icon the icon to use
     */
    public JToggleButtonExt(Icon icon) {
        super(icon);
    }

    /**
     * Scales the font of this button
     * @param factor the scale factor
     * @return this
     */
    public JToggleButtonExt scaleFont(double factor) {
        ExtUtilities.scaleFont(this, factor);
        return this;
    }
    
    /**
     * When the button performs an action event, send the command integer to the callback function
     * @return this
     */
    public JToggleButtonExt onActionPerformed(final Function1<? super JToggleButtonExt, ?> callback) {
        addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                callback.apply(JToggleButtonExt.this);
            }
        });
        return this;
    }
    
    /**
     * Returns the user object as a typed instance
     * @param <T> the requested type
     * @param type the cast type
     * @return the user object or null (if null or not <: type)
     */
    public <T> T getUserObject(Class<T> type) {
        if(userObject == null) return null;
        if(type.isAssignableFrom(userObject.getClass())) return type.cast(userObject);
        return null;
    }

    /**
     * Set the user object of this button
     * @param o the user object to set
     * @return this
     */
    public JToggleButtonExt setUserObject(Object o) {
        userObject = o;
        return this;
    }

    /**
     * Set the button group of this control
     * @param group the button group
     * @return this
     */
    public JToggleButtonExt group(ButtonGroup group) {
        group.add(this);
        return this;
    }

    /**
     * Set the label of this button
     * @param text the text to set
     * @return this
     */
    public JToggleButtonExt withLabel(String text) {
        setText(text);
        return this;
    }

    /**
     * Set the selected state of this button
     * @param b the state
     * @return this
     */
    public JToggleButtonExt selected(boolean b) {
        setSelected(b);
        return this;
    }

    /**
     * Set the tool tip text and return this
     * @param newTip the text to set
     * @return this
     */
    public JToggleButtonExt withToolTipText(String newTip) {
        setToolTipText(newTip);
        return this;
    }

    public JToggleButtonExt alignLabelLeft() {
        setHorizontalAlignment(SwingConstants.LEFT);
        return this;
    }
}
